/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.logiclander.ricemine.services.identity;

import com.logiclander.ricemine.utils.LdapUtilities;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.kuali.rice.kim.bo.entity.dto.KimEntityAddressInfo;
import org.kuali.rice.kim.util.KimConstants;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;

/**
 *
 * @author tcarroll
 */
public class LdapKimEntityAddressInfoMapper implements ContextMapper {

  private final Log log = LogFactory.getLog(getClass());
  private String lineOneAttributeName = null;
//  private String lineTwoAttributeName = null;
//  private String lineThreeAttributeName = null;
  private String cityNameAttributeName = null;
  private String stateCodeAttributeName = null;
  private String postalCodeAttributeName = null;
  private String countryCodeAttributeName = null;
  private String suppressionAttributeName = null;

//beg: methods required by ContextMapper interface
  public Object mapFromContext(Object ctx) {
    validateConfiguration();
    KimEntityAddressInfo keai = new KimEntityAddressInfo();
    try {
      DirContextAdapter context = (DirContextAdapter) ctx;
      // currently, this assumes that an entity only has one address (the one aligned
      // with this ldap record.  this is a decent assumption for now, but a configurable
      // option for either doing it this way or mapping multiple addresses would be better
      // perhaps some organizations have multi-valued attributes that list addresses

      // the entityAddressId is a synthetic identifier for the instance of an entity address.
      // this should be unique in the system, but there is no graceful way to do this
      // from an ldap mapping
      keai.setEntityAddressId(this.determineEntityAddressId(context));
      keai.setEntityTypeCode(this.determineEntityTypeCode(context));
      keai.setAddressTypeCode(this.determineAddressTypeCode(context));
      keai.setLine1Unmasked(this.determineLine1Unmasked(context));
      keai.setCityNameUnmasked(this.determineCityNameUnmasked(context));
      keai.setStateCodeUnmasked(this.determineStateCodeUnmasked(context));
      keai.setCountryCodeUnmasked(this.determineCountryCodeUnmasked(context));
      keai.setPostalCodeUnmasked(this.determinePostalCodeUnmasked(context));
      String suppressionAttributeValue = this.determineSuppressionAttributeValue(context);
      if (suppressionAttributeValue != null && suppressionAttributeValue.equalsIgnoreCase("TRUE")) {
        keai.setSuppressAddress(true);
        keai.setLine1(KimConstants.RESTRICTED_DATA_MASK);
        keai.setCityNameUnmasked(KimConstants.RESTRICTED_DATA_MASK);
        keai.setStateCode("XX");
        keai.setCountryCode("XX");
        keai.setPostalCode("00000");
      } else {
        keai.setSuppressAddress(false);
        keai.setLine1(keai.getLine1Unmasked());
        keai.setCityName(keai.getCityNameUnmasked());
        keai.setStateCode(keai.getStateCodeUnmasked());
        keai.setCountryCode(keai.getCountryCodeUnmasked());
        keai.setPostalCode(keai.getPostalCodeUnmasked());
      }
      keai.setActive(this.determineActive(context));
      keai.setDefault(this.determineDefault(context));
    } catch (Throwable t) {
      log.error("Error in ContextMapper", t);
      String msg = "ContextMapper failed to create a LdapRecord from the specified Context: " + ctx;
      throw new RuntimeException(msg, t);
    }
    if (log.isDebugEnabled()) {
      log.debug("mapped LdapKimEntityAddress:"
              + "(entityAddressId=" + keai.getEntityAddressId() + ")"
              + "(addressTypeCode=" + keai.getAddressTypeCode() + ")"
              + "(postalCode=" + keai.getPostalCode() + ")"
              + "(isActive=" + keai.isActive() + ")"
              + "(isDefault=" + keai.isDefault() + ")"
              + "(isSuppressAddress=" + keai.isSuppressAddress() + ")");
    }
    return keai;
  }

//end: methods required by ContextMapper interface
//beg: helper methods
  public String getCityNameAttributeName() {
    return cityNameAttributeName;
  }

  public void setCityNameAttributeName(String cityNameAttributeName) {
    this.cityNameAttributeName = cityNameAttributeName;
  }

  public String getLineOneAttributeName() {
    return lineOneAttributeName;
  }

  public void setLineOneAttributeName(String lineOneAttributeName) {
    this.lineOneAttributeName = lineOneAttributeName;
  }

  public String getStateCodeAttributeName() {
    return stateCodeAttributeName;
  }

  public void setStateCodeAttributeName(String stateCodeAttributeName) {
    this.stateCodeAttributeName = stateCodeAttributeName;
  }

  public String getCountryCodeAttributeName() {
    return countryCodeAttributeName;
  }

  public void setCountryCodeAttributeName(String countryCodeAttributeName) {
    this.countryCodeAttributeName = countryCodeAttributeName;
  }

  public String getPostalCodeAttributeName() {
    return this.postalCodeAttributeName;
  }

  public void setPostalCodeAttributeName(String attrName) {
    this.postalCodeAttributeName = attrName;
  }

  public String getSuppressionAttributeName() {
    return this.suppressionAttributeName;
  }

  public void setSuppressionAttributeName(String attrName) {
    this.suppressionAttributeName = attrName;
  }

  protected String determineEntityAddressId(DirContextAdapter context) {
	return ("1");//is there an ldap attribute for this?  
  }
  
  protected String determineEntityTypeCode(DirContextAdapter context) {
	  return "PERSON";//is there an ldap attribute for this?
  }
  
  protected String determineAddressTypeCode(DirContextAdapter context) {
	  return "WRK";//is there an ldap attribute for this?
  }
  
  protected String determineLine1Unmasked(DirContextAdapter context) {
	  return LdapUtilities.materialize(context.getStringAttribute(lineOneAttributeName));
  }
  
  protected String determineCityNameUnmasked(DirContextAdapter context) {
	  return LdapUtilities.materialize(context.getStringAttribute(cityNameAttributeName));
  }
  
  protected String determineStateCodeUnmasked(DirContextAdapter context) {
	  return LdapUtilities.materialize(context.getStringAttribute(stateCodeAttributeName));
  }
  
  protected String determineCountryCodeUnmasked(DirContextAdapter context) {
	  return LdapUtilities.materialize(context.getStringAttribute(countryCodeAttributeName));
  }
  
  protected String determinePostalCodeUnmasked(DirContextAdapter context) {
	  return LdapUtilities.materialize(context.getStringAttribute(postalCodeAttributeName));
  }
  
  protected String determineSuppressionAttributeValue(DirContextAdapter context) {
	  return context.getStringAttribute(suppressionAttributeName);
  }
  
  protected boolean determineActive(DirContextAdapter context) {
	  return true;//is there an ldap attribute for this?
  }
  
  protected boolean determineDefault(DirContextAdapter context) {
	  return true;//is there an ldap attribute for this?
  }
  
  private void validateConfiguration() {
    if (cityNameAttributeName == null) {
      String msg = "The property 'cityNameAttributeName' must be set.";
      throw new IllegalStateException(msg);
    }
    if (lineOneAttributeName == null) {
      String msg = "The property 'lineOneAttributeName' must be set.";
      throw new IllegalStateException(msg);
    }
    if (stateCodeAttributeName == null) {
      String msg = "The property 'stateCodeAttributeName' must be set.";
      throw new IllegalStateException(msg);
    }
    if (countryCodeAttributeName == null) {
      String msg = "The property 'countryCodeAttributeName' must be set.";
      throw new IllegalStateException(msg);
    }
    if (postalCodeAttributeName == null) {
      String msg = "The property 'postalCodeAttributeName' must be set.";
      throw new IllegalStateException(msg);
    }
    if (suppressionAttributeName == null) {
      String msg = "The property 'suppressionAttributeName' must be set.";
      throw new IllegalStateException(msg);
    }
  }
//end: helper methods
}
